﻿using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
using TemplateEngineWithChart.Docx;
using TemplateEngineWithChart.Docx.FullExample;
using TemplateEngineWithChart.Docx.TemplateCustomContent;

namespace ConsoleApp1.Template1
{
    internal class InputTemplate
    {
        internal Content fValuesToFill = new Content();

        public InputTemplate()
        {
        }

        /// <summary>
        /// 团体基本信息
        /// </summary>
        public void SetDictOrgInfo(OrgInfo orgInfo)
        {
            // 顶级属性
            if (orgInfo != null && orgInfo.DictOrgInfo != null)
            {
                foreach (var item in orgInfo.DictOrgInfo)
                {
                    FieldContent fieldContent = new FieldContent(item.Key, item.Value);
                    fieldContent.IsHidden = string.IsNullOrEmpty(item.Value);
                    this.fValuesToFill.Fields.Add(fieldContent);
                }
            }
        }

        /// <summary>
        /// 人员构成
        /// </summary>
        public void SetStaffComposition(StaffComposition staffComposition)
        {
            // 人员构成表格
            TableContent tableStaffComposition = new TableContent("人员构成");
            this.fValuesToFill.Tables.Add(tableStaffComposition);

            // 人员构成柱状图
            ChartContent chartStaffComposition = new ChartContent("人员构成柱状图", new ChartData()
            {
                SeriesNames = new[] { "男性人数", "女性人数" },
                CategoryDataType = ChartDataType.String
            });
            this.fValuesToFill.Charts.Add(chartStaffComposition);
            if (staffComposition == null)
            {
                tableStaffComposition.Hide();
                chartStaffComposition.Hide();
                return;
            }

            if (staffComposition.TableStaffComposition != null && staffComposition.TableStaffComposition.Rows.Count > 0)
            {
                for (int i = 0; i < staffComposition.TableStaffComposition.Rows.Count; i++)
                {
                    List<FieldContent> rows = staffComposition.TableStaffComposition.Rows[i].DataRowToFields(staffComposition.TableStaffComposition.TableName);
                    tableStaffComposition.AddRow(rows.ToArray());
                }
            }
            else
            {
                tableStaffComposition.Hide();
            }

            if (staffComposition.StaffCompositionCategoryNames != null &&
                staffComposition.StaffCompositionCategoryNames.Length > 0 &&
                staffComposition.StaffCompositionValues != null &&
                staffComposition.StaffCompositionValues.Length > 0)
            {
                chartStaffComposition.ChartData.Values = staffComposition.StaffCompositionValues;
                chartStaffComposition.ChartData.CategoryNames = staffComposition.StaffCompositionCategoryNames;
            }
            else
            {
                chartStaffComposition.Hide();
            }
        }

        /// <summary>
        /// 项目参检
        /// </summary>
        public void SetTableExamItem(DataTable dt)
        {
            // 项目参检表格
            TableContent tableExamItem = new TableContent("项目参检");
            this.fValuesToFill.Tables.Add(tableExamItem);
            if (dt != null && dt.Rows.Count > 0)
            {
                for (int i = 0; i < dt.Rows.Count; i++)
                {
                    List<FieldContent> rows = dt.Rows[i].DataRowToFields(dt.TableName);
                    tableExamItem.AddRow(rows.ToArray());
                }
            }
            else
            {
                tableExamItem.Hide();
            }
        }

        /// <summary>
        /// 年龄分布
        /// </summary>
        public void SetAgeMap(AgeMap ageMap)
        {
            // 团体年龄分布表格
            TableContent tableAgeMap = new TableContent("团体年龄分布");
            this.fValuesToFill.Tables.Add(tableAgeMap);

            // 团体年龄分布饼状图
            ChartContent chartAgeMap = new ChartContent("团体年龄分布饼状图", new ChartData()
            {
                SeriesNames = new[] { "数量" },
                CategoryDataType = ChartDataType.String
            });
            this.fValuesToFill.Charts.Add(chartAgeMap);
            if (ageMap == null)
            {
                tableAgeMap.Hide();
                chartAgeMap.Hide();
                return;
            }

            if (ageMap.TableAgeMap != null && ageMap.TableAgeMap.Rows.Count > 0)
            {
                for (int i = 0; i < ageMap.TableAgeMap.Rows.Count; i++)
                {
                    List<FieldContent> rows = ageMap.TableAgeMap.Rows[i].DataRowToFields(ageMap.TableAgeMap.TableName);
                    tableAgeMap.AddRow(rows.ToArray());
                }
            }
            else
            {
                tableAgeMap.Hide();
            }

            if (ageMap.AgeMapCategoryNames != null &&
                ageMap.AgeMapCategoryNames.Length > 0 &&
                ageMap.AgeMapValues != null &&
                ageMap.AgeMapValues.Length > 0)
            {
                chartAgeMap.ChartData.Values = ageMap.AgeMapValues;
                chartAgeMap.ChartData.CategoryNames = ageMap.AgeMapCategoryNames;
            }
            else
            {
                chartAgeMap.Hide();
            }
        }

        /// <summary>
        /// 健康问题分析
        /// </summary>
        public void SetHealthAnalysis(HealthAnalysis healthAnalysis)
        {
            // 健康问题分析表格
            TableContent tableHealthAnalysis = healthAnalysis == null ? new TableContent("健康问题分析") : healthAnalysis.TableHealth.DataTableToTableContent("健康问题分析");
            this.fValuesToFill.Tables.Add(tableHealthAnalysis);

            // 合计十大统计柱状图
            ChartContent chartAllTop10 = new ChartContent("合计十大统计柱状图", new ChartData()
            {
                SeriesNames = new[] { "男性人数", "女性人数", "合计" },
                CategoryDataType = ChartDataType.String
            });
            this.fValuesToFill.Charts.Add(chartAllTop10);

            // 女性十大统计
            ListContent listFemalTop10 = new ListContent("女性十大统计");
            this.fValuesToFill.Lists.Add(listFemalTop10);

            // 男性十大统计
            ListContent listMalTop10 = new ListContent("男性十大统计");
            this.fValuesToFill.Lists.Add(listMalTop10);

            if (healthAnalysis == null)
            {
                tableHealthAnalysis.Hide();
                chartAllTop10.Hide();
                listFemalTop10.Hide();
                listMalTop10.Hide();
            }
            else
            {
                if (healthAnalysis.AllTop10CategoryNames != null &&
                    healthAnalysis.AllTop10CategoryNames.Length > 0 &&
                    healthAnalysis.AllTop10Values != null &&
                    healthAnalysis.AllTop10Values.Length > 0)
                {
                    chartAllTop10.ChartData.Values = healthAnalysis.AllTop10Values;
                    chartAllTop10.ChartData.CategoryNames = healthAnalysis.AllTop10CategoryNames;
                }
                else
                {
                    chartAllTop10.Hide();
                }

                if (healthAnalysis.MaleTop10 != null && healthAnalysis.MaleTop10.Length > 0)
                {
                    foreach (var item in healthAnalysis.MaleTop10)
                    {
                        listMalTop10.AddItem(new FieldContent("男性十大统计.ConclusionName", item));
                    }
                }
                else
                {
                    listMalTop10.Hide();
                }

                if (healthAnalysis.FemaleTop10 != null && healthAnalysis.FemaleTop10.Length > 0)
                {
                    foreach (var item in healthAnalysis.FemaleTop10)
                    {
                        listFemalTop10.AddItem(new FieldContent("女性十大统计.ConclusionName", item));
                    }
                }
                else
                {
                    listFemalTop10.Hide();
                }
            }
        }

        /// <summary>
        /// 员工健康问题
        /// </summary>
        public void SetAllHealthProblem(DataTable allConclusions, List<DataRow> allPatients)
        {
            this.fValuesToFill.Repeats.Add(this.SetHealthProblem("所有员工健康问题", allConclusions.AsEnumerable().ToList(), allPatients));
        }

        /// <summary>
        /// 男性员工健康问题
        /// </summary>
        public void SetMaleHealthProblem(DataTable allConclusions, List<DataRow> allPatients)
        {
            this.fValuesToFill.Repeats.Add(this.SetHealthProblem("男性员工健康问题", allConclusions.AsEnumerable().Where(p => allPatients.Select(f => f.DataRowToString("KeyConclusion")).Contains(p.DataRowToString("KeyConclusion"))).ToList(), allPatients));
        }

        /// <summary>
        /// 女性员工健康问题
        /// </summary>
        public void SetFemaleHealthProblem(DataTable allConclusions, List<DataRow> allPatients)
        {
            this.fValuesToFill.Repeats.Add(this.SetHealthProblem("女性员工健康问题", allConclusions.AsEnumerable().Where(p => allPatients.Select(f => f.DataRowToString("KeyConclusion")).Contains(p.DataRowToString("KeyConclusion"))).ToList(), allPatients));
        }

        /// <summary>
        /// 全体员工体检结果汇总
        /// </summary>
        public void SetAllResults(DataTable dt)
        {
            RepeatContent typeGroupContent = new RepeatContent("团体全体人员汇总");
            if (dt != null && dt.Rows.Count > 0)
            {
                for (int i = 0; i < dt.Rows.Count; i++)
                {
                    typeGroupContent.AddItem(dt.Rows[i].DataRowToFields(dt.TableName).ToArray());
                }
            }
            else
            {
                typeGroupContent.Hide();
            }

            this.fValuesToFill.Repeats.Add(typeGroupContent);
        }

        public void FillData(string inputFile, string outputFile)
        {
            File.Copy(inputFile, outputFile);
            using (var outputDocument = new TemplateProcessor(outputFile))
            {
                outputDocument.SetRemoveContentControls(true);
                outputDocument.FillContent(this.fValuesToFill);
                outputDocument.SaveChanges();
            }
        }

        private RepeatContent SetHealthProblem(string name, List<DataRow> allConclusions, List<DataRow> allPatients)
        {
            List<HealthProblem> healthProblems = new List<HealthProblem>();
            if (allConclusions != null && allConclusions.Count > 0)
            {
                var typeGroup = allConclusions.GroupBy(p => p.DataRowToString("ConclusionTypeName"));
                foreach (var type in typeGroup)
                {
                    // 结论词
                    var rows = allConclusions.Where(p => p.DataRowToString("ConclusionTypeName") == type.Key).ToList();
                    healthProblems.Add(new HealthProblem(name, type.Key, rows, allPatients));
                }
            }

            RepeatContent repeatAllHealth = new RepeatContent(name);
            repeatAllHealth.IsHidden = healthProblems.Count <= 0;
            foreach (var item in healthProblems)
            {
                FieldContent typeFieldContent = new FieldContent($"{name}.ConclusionTypeName", item.ConclusionTypeName);
                typeFieldContent.IsHidden = string.IsNullOrEmpty(item.ConclusionTypeName);

                RepeatContent conclusionContent = new RepeatContent($"{name}.结论词");
                conclusionContent.IsHidden = item.Conclusions == null || item.Conclusions.Count == 0;
                foreach (var conclusion in item.Conclusions)
                {
                    ListItemContent itemContent = new ListItemContent();
                    foreach (var dic in conclusion.DictConclusion)
                    {
                        FieldContent fieldContent = new FieldContent(dic.Key, dic.Value);
                        fieldContent.IsHidden = string.IsNullOrEmpty(dic.Value);
                        itemContent.AddField(fieldContent);
                    }

                    TableContent tableContent = conclusion.Patients.DataTableToTableContent($"{name}.结论词.体检人员名单");
                    itemContent.AddTable(tableContent);

                    conclusionContent.AddItem(itemContent);
                }

                repeatAllHealth.AddItem(typeFieldContent, conclusionContent);
            }

            return repeatAllHealth;
        }
    }

    /// <summary>
    /// 团体基本信息
    /// </summary>
    internal class OrgInfo
    {
        /// <summary>
        /// 团体基本信息
        /// </summary>
        public Dictionary<string, string> DictOrgInfo { get; set; }

        public OrgInfo(DataTable dt)
        {
            if (dt != null)
            {
                this.DictOrgInfo = new Dictionary<string, string>()
                {
                    { "团体基本信息.DatePrinted", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") }
                };
                for (int i = 0; i < dt.Columns.Count; i++)
                {
                    DataColumn dc = dt.Columns[i];
                    if (dc.ColumnName == "DateFinished" || dc.ColumnName == "DateReservation")
                    {
                        DateTime? time = dt.Rows[0].DataRowToDateTimeNull(dc.ColumnName);
                        this.DictOrgInfo.Add($"{dt.TableName}.{dc.ColumnName}", time.HasValue ? time.Value.ToString("yyyy-MM-dd") : string.Empty);
                    }
                    else
                    {
                        this.DictOrgInfo.Add($"{dt.TableName}.{dc.ColumnName}", dt.Rows[0].DataRowToString(dc.ColumnName));
                    }
                }
            }
        }
    }

    /// <summary>
    /// 人员构成
    /// </summary>
    internal class StaffComposition
    {
        /// <summary>
        /// 人员构成表格
        /// </summary>
        public DataTable TableStaffComposition { get; set; }

        /// <summary>
        /// 人员构成柱状图X轴
        /// </summary>
        public string[] StaffCompositionCategoryNames { get; set; }

        /// <summary>
        /// 人员构成柱状图Y轴
        /// </summary>
        public double[][] StaffCompositionValues { get; set; }

        public StaffComposition(DataTable dt)
        {
            this.TableStaffComposition = dt;
            if (dt != null && dt.Rows.Count > 0)
            {
                this.StaffCompositionCategoryNames = dt.AsEnumerable().Select(p => p.DataRowToString("PatientStateName")).ToArray();
                this.StaffCompositionValues = new double[][]
                {
                    dt.AsEnumerable().Select(p => Convert.ToDouble(p.DataRowToDecimalNull("SumMalepercentage").HasValue ? p.DataRowToDecimalNull("SumMalepercentage").Value : 0)).ToArray(),
                    dt.AsEnumerable().Select(p => Convert.ToDouble(p.DataRowToDecimalNull("SumFemalepercentage").HasValue ? p.DataRowToDecimalNull("SumFemalepercentage").Value : 0)).ToArray()
                };
            }
        }
    }

    /// <summary>
    /// 年龄分布
    /// </summary>
    internal class AgeMap
    {
        /// <summary>
        /// 团体年龄分布表格
        /// </summary>
        public DataTable TableAgeMap { get; set; }

        /// <summary>
        /// 团体年龄分布饼状图X轴
        /// </summary>
        public string[] AgeMapCategoryNames { get; set; }

        /// <summary>
        /// 团体年龄分布饼状图Y轴
        /// </summary>
        public double[][] AgeMapValues { get; set; }

        public AgeMap(DataTable dt)
        {
            this.TableAgeMap = dt;
            if (dt != null && dt.Rows.Count > 0)
            {
                this.AgeMapCategoryNames = dt.AsEnumerable().Select(p => p.DataRowToString("GroupName")).ToArray();
                this.AgeMapValues = new double[][]
                {
                    dt.AsEnumerable().Select(p=>Convert.ToDouble(p.DataRowToDecimalNull("GroupNum").HasValue?p.DataRowToDecimalNull("GroupNum").Value:0)).ToArray()
                };

            }
        }
    }

    /// <summary>
    /// 健康问题分析
    /// </summary>
    internal class HealthAnalysis
    {
        /// <summary>
        /// 健康问题分析表格
        /// </summary>
        public DataTable TableHealth { get; set; }

        /// <summary>
        /// 女性十大统计
        /// </summary>
        public string[] FemaleTop10 { get; set; }

        /// <summary>
        /// 男性十大统计
        /// </summary>
        public string[] MaleTop10 { get; set; }

        /// <summary>
        /// 合计十大统计X轴
        /// </summary>
        public string[] AllTop10CategoryNames { get; set; }

        /// <summary>
        /// 合计十大统计Y轴
        /// </summary>
        public double[][] AllTop10Values { get; set; }

        public HealthAnalysis(DataTable tableHealth, DataTable dtAllTop10, DataTable dtMaleTop10, DataTable dtFemaleTop10)
        {
            this.TableHealth = tableHealth;
            if (dtAllTop10 != null && dtAllTop10.Rows.Count > 0)
            {
                this.AllTop10CategoryNames = dtAllTop10.AsEnumerable().Select(p => p.DataRowToString("ConclusionName")).ToArray();
                this.AllTop10Values = new double[][]
                {
                    dtAllTop10.AsEnumerable().Select(p=>Convert.ToDouble(p.DataRowToDecimalNull("Male").HasValue?p.DataRowToDecimalNull("Male").Value:0)).ToArray(),
                    dtAllTop10.AsEnumerable().Select(p=>Convert.ToDouble(p.DataRowToDecimalNull("Female").HasValue?p.DataRowToDecimalNull("Female").Value:0)).ToArray(),
                    dtAllTop10.AsEnumerable().Select(p=>Convert.ToDouble(p.DataRowToDecimalNull("ConclusionNum").HasValue?p.DataRowToDecimalNull("ConclusionNum").Value:0)).ToArray()
                };
            }

            if (dtMaleTop10 != null && dtMaleTop10.Rows.Count > 0)
            {
                this.MaleTop10 = dtMaleTop10.AsEnumerable().Select(p => p.DataRowToString("ConclusionName")).ToArray();
            }

            if (dtFemaleTop10 != null && dtFemaleTop10.Rows.Count > 0)
            {
                this.FemaleTop10 = dtFemaleTop10.AsEnumerable().Select(p => p.DataRowToString("ConclusionName")).ToArray();
            }
        }
    }

    /// <summary>
    /// 健康问题
    /// </summary>
    internal class HealthProblem
    {
        /// <summary>
        /// 结论词分类
        /// </summary>
        public string ConclusionTypeName { get; set; }

        /// <summary>
        /// 结论词
        /// </summary>
        public List<Conclusion> Conclusions { get; set; }

        public HealthProblem(string name, string conclusionTypeName, List<DataRow> allConclusions, List<DataRow> allPatients)
        {
            this.ConclusionTypeName = conclusionTypeName;
            if (allConclusions != null && allConclusions.Count > 0)
            {
                this.Conclusions = new List<Conclusion>();
                foreach (var row in allConclusions)
                {
                    Conclusion item = new Conclusion()
                    {
                        DictConclusion = new Dictionary<string, string>()
                    };
                    for (int i = 0; i < row.Table.Columns.Count; i++)
                    {
                        item.DictConclusion.Add($"{name}.结论词.{row.Table.Columns[i].ColumnName}", row.DataRowToString(row.Table.Columns[i].ColumnName));
                    }

                    var patientRows = allPatients.Where(p => p.DataRowToString("KeyConclusion") == row.DataRowToString("KeyConclusion"));
                    if (patientRows != null && patientRows.Count() > 0)
                    {
                        DataTable dt = patientRows.CopyToDataTable();
                        dt.TableName = "{name}.结论词.体检人员名单";
                        item.Patients = dt;
                    }

                    this.Conclusions.Add(item);
                }
            }
        }
    }

    internal class Conclusion
    {
        /// <summary>
        /// 结论词
        /// </summary>
        public Dictionary<string, string> DictConclusion { get; set; }

        /// <summary>
        /// 人员名单
        /// </summary>
        public DataTable Patients { get; set; }
    }
}
